<template>
  <div class="padding-box-100">
    <h1>{{ msg }}</h1>
    <div class="virtual-list" @scroll="scroll">
      <div :style="boxStyle"></div>
      <ul class="virtual-list-container" :style="containerStyle">
        <li v-for="item in renderList" :key="item">{{ item }}</li>
      </ul>
    </div>
  </div>
</template>

<script>
import {defineComponent, ref, computed} from 'vue';
import {throttle} from 'lodash';

export default defineComponent({
  name: 'VirtualList',
  props: {
    msg: String,
  },
  setup() {
    let list = [];
    const testLength = 50000;
    for (let i = 0; i < testLength; i++) {
      list.push(i)
    }
    const clientHeight = ref(500);
    const startIndex = ref(0);
    //计算容器高度
    const boxHeight = 30 * testLength;
    const boxStyle = ref(`height: ${boxHeight}px`);

    const renderNum = Math.ceil(clientHeight.value / 30);

    const renderList = computed(() => {
      return list.slice(startIndex.value, startIndex.value + renderNum);
    });
    const containerStyle = ref('');

    const scroll = throttle(function (event) {

      containerStyle.value = `transform: translateY(${event.target.scrollTop}px);`;
      if (event.target.scrollTop + event.target.clientHeight === boxHeight) {
        startIndex.value = testLength - renderNum - 1;
      } else {
        startIndex.value = Math.floor(event.target.scrollTop / 30);
      }
    }, 100)

    return {
      clientHeight,
      boxStyle,
      renderList,
      scroll,
      containerStyle,
    }
  }
})


</script>

<style scoped>
.virtual-list {
  height: 500px;
  overflow: auto;
  position: relative;
}

.virtual-list-container {
  transition: all .2s;
  will-change: translateY;
}

a {
  color: #42b983;
}

ul {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
}

li {
  line-height: 29px;
  background-color: #ccc;
  border-bottom: 1px solid red;
}
</style>

